<?php
// +----------------------------------------------------------------------
// | INPHP
// | Copyright (c) 2023 https://inphp.cc All rights reserved.
// | Licensed ( https://opensource.org/licenses/MIT )
// | Author: 幺月儿(https://gitee.com/lulanyin) Email: inphp@qq.com
// +----------------------------------------------------------------------
// | 授权
// +----------------------------------------------------------------------
namespace app\sso\http\api;

use app\sso\http\api\admin\thirdParty;
use app\sso\model\UserAuthModel;
use app\sso\model\UserModel;
use Inphp\Core\Attributes\Method;
use Inphp\Core\Middlewares;
use Inphp\Core\Modules;
use Inphp\Core\Object\Message;
use Inphp\Core\Util\Str;

class auth
{
    /**
     * 登陆授权
     * @return Message
     */
    #[Method(Method::POST)] public function index(): Message
    {
        //支持第三方插件授权
        $plugin = POST("plugin");
        $plugin = !empty($plugin) ? Str::trim($plugin) : null;
        if (!empty($plugin)) {
            //使用第三方插件处理
            return $this->plugin($plugin);
        }
        //账号
        $account = POST("account");
        $account = !empty($account) ? Str::trim($account) : null;
        if (empty($account)) {
            return httpMessage("缺少账号");
        }
        //登陆方式
        $passwordType = POST("passwordType");
        $passwordType = $passwordType == "sms" ? "sms" : "password";
        //密码/短信验证码
        $password = POST("password");
        $password = !empty($password) ? $password : null;
        if (empty($password)) {
            return httpMessage($passwordType == "sms" ? 20 : 1, "缺少".($passwordType == "sms" ? "短信验证码" : "登陆密码"));
        }
        //国家代码
        $countryCode = POST("countryCode");
        if (!empty($countryCode)) {
            if (stripos($countryCode, "+") === 0) {
                $countryCode = substr($countryCode, 1);
            }
        }
        //默认使用中国号码
        $countryCode = is_numeric($countryCode) && $countryCode >= 0 ? $countryCode : 86;
        if ($passwordType === "sms") {
            //检测手机号码
            if (!Str::isPhoneNumber($account, $countryCode)) {
                return httpMessage("手机号码格式错误");
            }
            //校验短信验证码
            if (!\app\sso\lib\sms\SMS::verify($countryCode, $account, $password, \app\sso\lib\sms\SMS::ACT_AUTH)) {
                return httpMessage(21);
            }
            //
            $user = UserModel::emptyQuery()
                ->where("countryCode", $countryCode)
                ->where("phone", $account)
                ->first();
            if (empty($user)) {
                //如果开启了短信一键登陆
                $config = Modules::getModule("sso")?->getConfig("auth") ?? [];
                if ($config["smsAutoRegister"] ?? false) {
                    //创建新账户
                    $user = [
                        "phone"         => $account,
                        "countryCode"   => $countryCode,
                        "nickname"      => $account,
                        "username"      => "u".makeOrderId(),
                        "ip"            => getIP(),
                        "state"         => 1
                    ];
                    //如果提交有推荐码进来
                    $ic = POST("ic", POST("vc"));
                    $ic = !empty($ic) ? Str::trim($ic) : null;
                    if (!empty($ic)) {
                        $parent = UserModel::emptyQuery()
                            ->where("username", $ic)
                            ->first();
                        if (!empty($parent)) {
                            $user["floor"] = $parent["floor"] + 1;
                            $user["parentUid"] = $parent["uid"];
                            $user["parentsUid"] = $parent["uid"].(!empty($parent["parentsUid"]) ? ",{$parent["parentsUid"]}" : "");
                        }
                    }
                    $db = UserModel::emptyQuery();
                    if (!$db->insert($user)) {
                        return httpMessage("账号注册失败");
                    }
                    $user["uid"] = $db->getLastInsertId();
                    //新账号注册事件
                    Middlewares::process("SSO_USER_REGISTER", $user);
                } else {
                    return httpMessage("未开放使用手机号码自动注册，请使用其它方式授权");
                }
            }
        } else {
            //强制需要验证码
            $vCode = POST("vCode");
            $vCode = !empty($vCode) ? Str::trim($vCode) : null;
            if (empty($vCode)) {
                return httpMessage(10);
            }
            $vCodeId = POST("vCodeId");
            $vCodeId = !empty($vCodeId) ? Str::trim($vCodeId) : 0;
            if (!matchVCode($vCode, $vCodeId)) {
                return httpMessage(11);
            }
            //验证密码
            $db = UserModel::emptyQuery();
            if (!empty($countryCode) && Str::isPhoneNumber($account, $countryCode)) {
                $db->where("phone", $account)
                    ->where("countryCode", $countryCode);
            } else {
                $db->where("username", $account);
            }
            $user = $db->first();
            if (empty($user)) {
                return httpMessage(32);
            }
            //校验密码
            if (!UserModel::verifyLoginPassword($password, $user["pwdKey"], $user["password"])) {
                return httpMessage(32);
            }
        }
        //账号状态
        if ($user["state"] == 0) {
            return httpMessage(33);
        }
        //授权成功
        list($token, $expireTime) = UserAuthModel::auth($user["uid"], $passwordType);
        Middlewares::process("SSO_USER_AUTH", $user);
        return httpMessage(compact("token", "expireTime"));
    }

    /**
     * 获取可用的第三方平台列表
     * @return array
     */
    public function thirdPartyList(): array
    {
        //先获取可用的APPID，如果没有，则也没有可用平台
        $appIdList = Modules::getModule("sso")->getConfig("thirdPartyApp");
        if (empty($appIdList)) {
            return [];
        }
        $pluginList = [];
        foreach ($appIdList as $app) {
            if ($app["state"] && !in_array($app["plugin"], $pluginList)) {
                $pluginList[] = $app["plugin"];
            }
        }
        if (empty($pluginList)) {
            return [];
        }
        $api = new thirdParty();
        $list = $api->list();
        $result = [];
        foreach ($list as $item) {
            if (in_array($item["plugin"], $pluginList)) {
                $result[] = [
                    "name"      => $item["name"],
                    "icon"      => $item["icon"],
                    "plugin"    => $item["plugin"]
                ];
            }
        }
        return $result;
    }

    /**
     * 其它平台，插件方式执行授权
     * @param string $name  插件名称
     * @return Message
     */
    private function plugin(string $name): Message
    {
        $name = !empty($name) ? Str::trim($name) : null;
        if (empty($name)) {
            //插件不存在
            return httpMessage("缺少授权插件名称参数");
        }
        //检测插件是否存在
        $controller = join("\\", ['app\sso\thirdParty', $name, 'auth']);
        if (!class_exists($controller)) {
            return httpMessage("无法处理该授权请求，没有该类型的授权插件");
        }
        //触发方法处理
        if (method_exists($controller, "process")) {
            $result = $controller::process();
            if ($result instanceof Message) {
                return $result;
            }
        }
        return httpMessage("未知处理");
    }
}